/**
 * 房间里头的人，每个人的抽象定义。
 * 
 * 房间里可能有多个人。
 * 每个人可能有多个Transport，0到1个Producer，n个Consumer
 * 
 * 想想这是为什么？
 */
class Peer {


    constructor(socketId, name) {

        this.id = socketId;
        this.name = name;
        // 类型是：WebRtcTransport
        this.transports = new Map();
        this.consumers = new Map();
        this.producers = new Map();
    }


    addTransport(transport) {
        this.transports.set(transport.id, transport);
    }


    async connectTransport(transportId, dtlsParameters) {
        // 找不到该transport ，就返回
        if (!this.transports.has(transportId)) return;

        // 找到这个人的transport， 建立连接
        // 客户端和服务端的transport在这一步终于连接了，两个transport根据 dtlsParameters 建立了最终链接
        const transport = this.transports.get(transportId);
        if (transport) {
            // https://mediasoup.org/documentation/v3/mediasoup/api/#webRtcTransport-connect
            // Provides the WebRTC transport
            await transport.connect({
                dtlsParameters: dtlsParameters,
            });
        }
    }

    async createProducer(producerTransportId, rtpParameters, kind, name) {
        //TODO handle null errors
        let producer = await this.transports.get(producerTransportId).produce({
          kind,
          rtpParameters
        })
        producer.clientName = name;
    
        // 往生产者集合里面塞入一个普通滴生产者
        this.producers.set(producer.id, producer)

        console.log(`生产完毕，生产者：${JSON.stringify(producer)}`);
    
        producer.on(
          'transportclose',
          function () {
            console.log('Producer transport close', { name: `${this.name}`, consumer_id: `${producer.id}` })
            producer.close()
            this.producers.delete(producer.id)
          }.bind(this)
        )
    
        return producer
      }
    
      async createConsumer(consumer_transport_id, producer_id, rtpCapabilities) {
        let consumerTransport = this.transports.get(consumer_transport_id)
    
        let consumer = null
        try {
          consumer = await consumerTransport.consume({
            producerId: producer_id,
            rtpCapabilities,
            paused: false //producer.kind === 'video',
          })
        } catch (error) {
          console.error('Consume failed', error)
          return
        }
    
        if (consumer.type === 'simulcast') {
          await consumer.setPreferredLayers({
            spatialLayer: 2,
            temporalLayer: 2
          })
        }
    
        this.consumers.set(consumer.id, consumer)
    
        consumer.on(
          'transportclose',
          function () {
            console.log('Consumer transport close', { name: `${this.name}`, consumer_id: `${consumer.id}` })
            this.consumers.delete(consumer.id)
          }.bind(this)
        )
    
        return {
          consumer,
          params: {
            producerId: producer_id,
            id: consumer.id,
            kind: consumer.kind,
            rtpParameters: consumer.rtpParameters,
            type: consumer.type,
            producerPaused: consumer.producerPaused
          }
        }
      }
    
      closeProducer(producer_id) {
        try {
          this.producers.get(producer_id).close()
        } catch (e) {
          console.warn(e)
        }
    
        this.producers.delete(producer_id)
      }
    
      getProducer(producer_id) {
        return this.producers.get(producer_id)
      }
    
      close() {
        this.transports.forEach((transport) => transport.close())
      }
    
      removeConsumer(consumer_id) {
        this.consumers.delete(consumer_id)
      }

}

module.exports = Peer;
